import asyncio
import logging
from typing import Dict, Optional, Callable
from app.db.session import SessionLocal
from app.crud.crud_post import post_crud, publish_job_crud
from app.crud.crud_xiaohongshu import xiaohongshu_account_crud, xiaohongshu_publish_log_crud
from app.services.playwright_service import playwright_service
from app.services.xiaohongshu_service import xiaohongshu_service

logger = logging.getLogger(__name__)

# 注册的handler字典
_handlers = {}


def register_handler(name: str):
    """装饰器：注册handler"""
    def decorator(func):
        _handlers[name] = func
        return func
    return decorator


def get_handler(name: str) -> Optional[Callable]:
    """获取handler函数"""
    return _handlers.get(name)


@register_handler("publishPostHandler")
async def publish_post_handler(params: str) -> Dict:
    """发布帖子的任务处理器"""
    db = SessionLocal()
    try:
        # 解析参数（通常是post_id）
        if not params:
            return {"success": False, "message": "Missing post_id parameter"}
        
        try:
            post_id = int(params.strip())
        except ValueError:
            return {"success": False, "message": f"Invalid post_id: {params}"}
        
        logger.info(f"Starting publish task for post_id: {post_id}")
        
        # 1. 从数据库获取帖子信息
        post = post_crud.get(db, post_id)
        if not post:
            return {"success": False, "message": f"Post {post_id} not found"}
        
        # 检查帖子状态
        if post.status != 1:  # 1-待发布
            return {"success": False, "message": f"Post {post_id} is not ready for publishing (status: {post.status})"}
        
        # 2. 更新帖子状态为发布中（可以添加一个新状态）
        post_crud.update_status(db, post_id=post_id, status=1)  # 保持待发布状态，或者添加新的"发布中"状态
        
        # 3. 准备发布数据
        post_data = {
            "title": post.title,
            "content": post.content,
            "images": post.images or [],
            "tags": post.tags or ""
        }
        
        # 4. 验证发布数据
        validation_result = playwright_service.validate_post_data(post_data)
        if not validation_result.get("valid", False):
            error_msg = "; ".join(validation_result.get("errors", []))
            post_crud.update_status(db, post_id=post_id, status=3, error_message=error_msg)
            return {"success": False, "message": f"Validation failed: {error_msg}"}
        
        # 5. 执行发布
        logger.info(f"Executing publish for post {post_id}")
        publish_result = await playwright_service.execute_publish(post_data)
        
        if publish_result.get("success", False):
            # 发布成功
            post_crud.update_status(db, post_id=post_id, status=2)  # 2-已发布
            
            # 更新发布任务状态
            publish_job = publish_job_crud.get_by_post_id(db, post_id)
            if publish_job:
                publish_job_crud.update_status(db, job_id=publish_job.id, status=3)  # 3-已完成
            
            logger.info(f"Post {post_id} published successfully")
            return {
                "success": True,
                "message": f"Post {post_id} published successfully",
                "post_url": publish_result.get("post_url")
            }
        else:
            # 发布失败
            error_msg = publish_result.get("message", "Unknown error")
            post_crud.update_status(db, post_id=post_id, status=3, error_message=error_msg)
            
            # 更新发布任务状态
            publish_job = publish_job_crud.get_by_post_id(db, post_id)
            if publish_job:
                publish_job_crud.update_status(db, job_id=publish_job.id, status=2)  # 2-已停止
            
            logger.error(f"Failed to publish post {post_id}: {error_msg}")
            return {
                "success": False,
                "message": f"Failed to publish post {post_id}: {error_msg}"
            }
    
    except Exception as e:
        logger.error(f"Error in publish_post_handler: {e}")
        
        # 更新状态为失败
        try:
            post_crud.update_status(db, post_id=post_id, status=3, error_message=str(e))
        except:
            pass
        
        return {
            "success": False,
            "message": f"Handler execution error: {str(e)}"
        }
    
    finally:
        db.close()


@register_handler("testHandler")
def test_handler(params: str) -> Dict:
    """测试用的handler"""
    logger.info(f"Test handler executed with params: {params}")
    return {
        "success": True,
        "message": f"Test handler completed with params: {params}"
    }


@register_handler("asyncTestHandler")
async def async_test_handler(params: str) -> Dict:
    """异步测试handler"""
    logger.info(f"Async test handler started with params: {params}")
    
    # 模拟异步操作
    await asyncio.sleep(2)
    
    logger.info(f"Async test handler completed with params: {params}")
    return {
        "success": True,
        "message": f"Async test handler completed with params: {params}"
    }


@register_handler("browserTestHandler")
async def browser_test_handler(params: str) -> Dict:
    """浏览器测试handler"""
    logger.info(f"Browser test handler started with params: {params}")
    
    try:
        # 测试浏览器环境
        result = await playwright_service.test_browser()
        
        return {
            "success": result.get("success", False),
            "message": f"Browser test: {result.get('message', 'Unknown result')}"
        }
    
    except Exception as e:
        logger.error(f"Error in browser test handler: {e}")
        return {
            "success": False,
            "message": f"Browser test failed: {str(e)}"
        }


@register_handler("xiaohongshuPublishHandler")
async def xiaohongshu_publish_handler(params: str) -> Dict:
    """小红书发布处理器"""
    db = SessionLocal()
    try:
        logger.info(f"小红书发布处理器调用，参数: {params}")
        
        # 解析参数
        if not params:
            return {"success": False, "message": "缺少参数"}
        
        try:
            import json
            param_data = json.loads(params)
        except json.JSONDecodeError:
            # 如果不是JSON，尝试解析为post_id
            try:
                post_id = int(params.strip())
                param_data = {"post_id": post_id}
            except ValueError:
                return {"success": False, "message": f"无效参数: {params}"}
        
        # 获取发布参数
        post_id = param_data.get("post_id")
        title = param_data.get("title")
        content = param_data.get("content")
        images = param_data.get("images", [])
        account_id = param_data.get("account_id")
        
        # 如果有post_id，从数据库获取帖子信息
        if post_id:
            post = post_crud.get(db, post_id)
            if not post:
                return {"success": False, "message": f"帖子 {post_id} 不存在"}
            
            title = title or post.title
            content = content or post.content
            images = images or (post.images if post.images else [])
        
        # 验证必要参数
        if not title or not content:
            return {"success": False, "message": "标题和内容不能为空"}
        
        # 获取账号信息
        if account_id:
            account = xiaohongshu_account_crud.get(db, id=account_id)
        else:
            account = xiaohongshu_account_crud.get_current_account(db)
        
        if not account:
            return {"success": False, "message": "未找到可用的小红书账号"}
        
        # 创建发布日志
        log = xiaohongshu_publish_log_crud.create_publish_log(
            db,
            account_id=account.id,
            post_id=post_id or 0,
            title=title,
            content=content,
            images=images
        )
        
        # 更新发布日志状态为发布中
        xiaohongshu_publish_log_crud.update_publish_status(
            db, log_id=log.id, status="publishing"
        )
        
        logger.info(f"开始发布到小红书: {title}")
        
        # 执行发布
        result = await xiaohongshu_service.publish_post(
            title=title,
            content=content,
            images=images
        )
        
        if result.get("success", False):
            # 发布成功
            xiaohongshu_publish_log_crud.update_publish_status(
                db, 
                log_id=log.id, 
                status="success",
                xiaohongshu_url=result.get("data", {}).get("url")
            )
            
            # 如果有关联的帖子，更新帖子状态
            if post_id:
                post_crud.update_status(db, post_id=post_id, status=2)  # 2-已发布
            
            logger.info(f"小红书发布成功: {title}")
            return {
                "success": True,
                "message": f"发布成功: {title}",
                "log_id": log.id,
                "xiaohongshu_url": result.get("data", {}).get("url")
            }
        else:
            # 发布失败
            error_msg = result.get("message", "未知错误")
            xiaohongshu_publish_log_crud.update_publish_status(
                db, 
                log_id=log.id, 
                status="failed",
                error_message=error_msg
            )
            
            # 如果有关联的帖子，更新帖子状态
            if post_id:
                post_crud.update_status(db, post_id=post_id, status=3, error_message=error_msg)
            
            logger.error(f"小红书发布失败: {error_msg}")
            return {
                "success": False,
                "message": f"发布失败: {error_msg}",
                "log_id": log.id
            }
            
    except Exception as e:
        logger.error(f"小红书发布处理器错误: {e}")
        return {
            "success": False,
            "message": f"处理器执行失败: {str(e)}"
        }
    finally:
        db.close()


@register_handler("xiaohongshuLoginCheckHandler")
async def xiaohongshu_login_check_handler(params: str) -> Dict:
    """小红书登录状态检查处理器"""
    try:
        logger.info(f"小红书登录状态检查处理器调用，参数: {params}")
        
        # 检查登录状态
        result = await xiaohongshu_service.check_login_status()
        
        if result.get("success", False) and result.get("is_logged_in", False):
            return {
                "success": True,
                "message": "登录状态正常",
                "is_logged_in": True
            }
        else:
            return {
                "success": False,
                "message": result.get("message", "登录状态检查失败"),
                "is_logged_in": False
            }
            
    except Exception as e:
        logger.error(f"小红书登录状态检查处理器错误: {e}")
        return {
            "success": False,
            "message": f"登录状态检查失败: {str(e)}",
            "is_logged_in": False
        }


@register_handler("xiaohongshuAccountSyncHandler")
async def xiaohongshu_account_sync_handler(params: str) -> Dict:
    """小红书账号数据同步处理器"""
    db = SessionLocal()
    try:
        logger.info(f"小红书账号数据同步处理器调用，参数: {params}")
        
        # 解析参数
        account_id = None
        if params:
            try:
                account_id = int(params.strip())
            except ValueError:
                pass
        
        # 获取账号
        if account_id:
            account = xiaohongshu_account_crud.get(db, id=account_id)
        else:
            account = xiaohongshu_account_crud.get_current_account(db)
        
        if not account:
            return {"success": False, "message": "未找到可用的小红书账号"}
        
        # 检查登录状态并获取最新信息
        login_result = await xiaohongshu_service.get_login_info()
        
        if not login_result.get("success", False):
            return {
                "success": False,
                "message": f"获取账号信息失败: {login_result.get('message', '未知错误')}"
            }
        
        # 更新账号信息
        data = login_result.get("data", {})
        user_stats = data.get("user_stats", {})
        
        from datetime import datetime
        update_data = {
            "last_login": datetime.utcnow()
        }
        
        # 更新统计数据
        if isinstance(user_stats, dict):
            if "followers" in user_stats:
                followers_str = user_stats["followers"]
                if isinstance(followers_str, str):
                    followers = int(followers_str.replace("万", "0000").replace("千", "000"))
                    update_data["followers"] = followers
            
            if "following" in user_stats:
                following_str = user_stats["following"]
                if isinstance(following_str, str):
                    following = int(following_str.replace("万", "0000").replace("千", "000"))
                    update_data["following"] = following
            
            if "posts" in user_stats:
                posts_str = user_stats["posts"]
                if isinstance(posts_str, str):
                    posts = int(posts_str.replace("万", "0000").replace("千", "000"))
                    update_data["posts"] = posts
        
        # 更新cookies
        cookies = data.get("cookies")
        if cookies:
            update_data["cookies"] = cookies
        
        xiaohongshu_account_crud.update(db, db_obj=account, obj_in=update_data)
        
        logger.info(f"小红书账号数据同步成功: {account.username}")
        return {
            "success": True,
            "message": f"账号数据同步成功: {account.username}",
            "account_id": account.id,
            "stats": user_stats
        }
        
    except Exception as e:
        logger.error(f"小红书账号数据同步处理器错误: {e}")
        return {
            "success": False,
            "message": f"账号数据同步失败: {str(e)}"
        }
    finally:
        db.close()


def get_all_handlers() -> Dict[str, Callable]:
    """获取所有注册的handlers"""
    return _handlers.copy()


def list_handlers() -> list:
    """列出所有handler名称"""
    return list(_handlers.keys())